package fr.ul.ade.secunde.ui.tablet;

import android.app.Activity;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentTransaction;

import com.actionbarsherlock.app.SherlockFragmentActivity;
import com.actionbarsherlock.view.Menu;
import com.actionbarsherlock.view.MenuItem;

import fr.ul.ade.R;
import fr.ul.ade.secunde.ui.HelpActionListener;
import fr.ul.ade.secunde.ui.LessonActionListener;
import fr.ul.ade.secunde.ui.PreferencesActionListener;
import fr.ul.ade.secunde.ui.ScheduleActionListener;
import fr.ul.ade.secunde.util.Bundles;

/**
 * Gestionnaire pour l'affichage des fragments pour la version tablette.
 * 
 * @author Michaël Schnell
 * @since Jul 2, 2013
 * 
 * @version 1.5
 */
public abstract class FragmentContentManager
		implements LessonActionListener, PreferencesActionListener,
		ScheduleActionListener, HelpActionListener {

	/**
	 * Activité contenant les fragments affichés.
	 */
	protected SherlockFragmentActivity activity;

	/**
	 * Transaction courante. Permet de garder une transaction ouverte entre
	 * plusieurs appels de méthodes sur le même receveur.
	 */
	protected FragmentTransaction mTransaction;

	/**
	 * Etats des fragments. Encode les fragments à afficher ainsi que leur
	 * position.
	 */
	protected FragmentState state;

	public FragmentContentManager(SherlockFragmentActivity activity) {
		this.activity = activity;
		this.state = new FragmentState();
		this.state.addState(FragmentState.SCHEDULE_LIST);
	}

	// --------------------------------------------------------
	//
	// Etat de l'activité
	//
	// --------------------------------------------------------

	/**
	 * Classe gérant et définissant les états possibles des fragments.
	 */
	protected static class FragmentState {
		private final Bundle values = new Bundle();
		static final int SCHEDULE_LIST = 1 << 0;
		static final int CREATE_SCHEDULE = 1 << 1;
		static final int EDIT_SCHEDULE = 1 << 2;
		static final int SCHEDULE_DETAILS = 1 << 3;
		static final int LESSON_LIST = 1 << 4;
		static final int LESSON_DETAILS = 1 << 5;
		static final int LESSON_CALENDAR = 1 << 6;
		static final int HELP = 1 << 7;
		static final int PREFERENCES = 1 << 8;
		static final int PREFERENCES_NOTIFICATIONS = 1 << 9;

		private int getState() {
			return this.values.getInt(Bundles.FRAGMENT_STATE, 0);
		}

		public void addState(int state) {
			this.values.putInt(Bundles.FRAGMENT_STATE, this.getState() | state);
		}

		public void removeState(int state) {
			this.values.putInt(Bundles.FRAGMENT_STATE, this.getState()
					& (~state));
		}

		public boolean hasState(int state) {
			return (this.getState() & state) != 0;
		}

		public void putId(String key, long id) {
			this.values.putLong(key, id);
		}

		public void removeId(String key) {
			this.values.remove(key);
		}
	}

	/**
	 * Fixe l'état des fragments de l'activité.
	 * 
	 * @param fragmentState
	 *            l'un des état définis dans l'interface {@link FragmentState}
	 */
	public void addState(int fragmentState) {
		this.state.addState(fragmentState);
		this.activity.invalidateOptionsMenu();
	}

	// --------------------------------------------------------
	//
	// Gestion des transitions
	//
	// --------------------------------------------------------

	@Override
	public void showScheduleDetails(long scheduleId, String scheduleName) {
		this.addState(FragmentState.SCHEDULE_DETAILS);
		this.state.putId(Bundles.SCHEDULE_DETAILS_ID, scheduleId);
	}

	@Override
	public void showCreateForm() {
		this.addState(FragmentState.CREATE_SCHEDULE);
	}

	@Override
	public void showEditForm(long scheduleId) {
		this.addState(FragmentState.EDIT_SCHEDULE);
		this.state.putId(Bundles.SCHEDULE_ID, scheduleId);
	}
	
	@Override
	public void showDeleteForm(long scheduleId, String scheduleName) {
		// TODO Auto-generated method stub
	}

	@Override
	public void showLessonList(long scheduleId) {
		this.addState(FragmentState.LESSON_LIST);
		this.state.putId(Bundles.SCHEDULE_ID, scheduleId);
	}

	@Override
	public void showPreferences() {
		this.addState(FragmentState.PREFERENCES);
	}

	@Override
	public void showNotificationsForm() {
		this.addState(FragmentState.PREFERENCES_NOTIFICATIONS);
	}

	@Override
	public void showLessonDetails(long scheduleId, long lessonId) {
		this.addState(FragmentState.LESSON_DETAILS);
		this.state.putId(Bundles.LESSON_DETAILS_SCHEDULE_ID, scheduleId);
		this.state.putId(Bundles.LESSON_DETAILS_ID, lessonId);
	}

	@Override
	public void showHelp() {
		this.addState(FragmentState.HELP);
	}

	/**
	 * Gère le retour en arrière pour le contenu des fragments.
	 * 
	 * @return {@code true} s'il faut appeler {@link Activity#onBackPressed()},
	 *         {@code false} si l'évènement à été complètement géré par cet
	 *         appel
	 */
	public boolean onBackPressed() {
		if (this.state.hasState(FragmentState.CREATE_SCHEDULE)) {
			this.state.removeState(FragmentState.CREATE_SCHEDULE);
			this.addState(FragmentState.SCHEDULE_LIST);
			return false;
		}

		// Other states : leave activity
		// - FragmentState.SCHEDULE_LIST
		return true;
	}

	// --------------------------------------------------------
	//
	// Gestion des fragments (ajout, suppression et animations)
	//
	// --------------------------------------------------------

	public abstract void initFragments();

	protected void showFragment(int containerId, Fragment fragment) {
		this.showFragment(containerId, fragment, null);
	}

	protected void showFragment(int containerId, Fragment fragment, String tag) {
		this.mTransaction.add(containerId, fragment, tag);
	}

	protected void hideFragment(String tag) {
		Fragment fragment = this.activity.getSupportFragmentManager()
				.findFragmentByTag(tag);
		if (fragment != null) {
			this.hideFragment(fragment);
		}
	}

	protected void hideFragment(Fragment fragment) {
		this.mTransaction.hide(fragment);
	}

	// --------------------------------------------------------
	//
	// Gestion des transactions
	//
	// --------------------------------------------------------

	protected void beginTransaction() {
		this.mTransaction = this.activity.getSupportFragmentManager()
				.beginTransaction();
	}

	protected void commitTransaction() {
		this.mTransaction.commit();
	}

	// --------------------------------------------------------
	//
	// Gestion de la barre d'action
	//
	// --------------------------------------------------------

	/**
	 * See {@link android.app.Activity#onCreateOptionsMenu(Menu)
	 * Activity.onCreateOptionsMenu(Menu)}.
	 */
	public boolean onCreateOptionsMenu(Menu menu) {
		// TODO Revoir la création des items
		// Il faudra soit passer à une version codée en XML, soit
		// récupérer l'icône ne passant par le thème courant

		menu.add(Menu.NONE,
				R.id.action_sync_all,
				Menu.NONE,
				R.string.action_sync).setIcon(R.drawable.refresh_white)
				.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);

		if (!this.state.hasState(FragmentState.CREATE_SCHEDULE)) {
			menu.add(Menu.NONE,
					R.id.action_create,
					Menu.NONE,
					R.string.action_create).setIcon(R.drawable.plus_white)
					.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
		}

		menu.add(Menu.NONE,
				R.id.action_preferences,
				Menu.NONE,
				R.string.action_preferences)
				.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);

		menu.add(Menu.NONE, R.id.action_help, Menu.NONE, R.string.action_help)
				.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);

		return true;
	}

	/**
	 * See {@link android.app.Activity#onOptionsItemSelected(MenuItem)
	 * Activity.onOptionsItemSelected(MenuItem)}.
	 */
	public boolean onOptionsItemSelected(MenuItem item) {
		switch (item.getItemId()) {
		case R.id.action_create:
			this.showCreateForm();
			return true;
		case R.id.action_preferences:
			this.showPreferences();
			return true;
		default:
		}

		return false;
	}
}// class FragmentManager